<?php

sys::uses("encoder");

class OutputEncode extends AbstractPlugin
{

    protected function __construct()
    {
        self::OnInit(new Event("Init"));
    }

    static function getInstance()
    {
        static $instance = null;
        if (is_null($instance)) {
        	
            $instance = new self();
        }

        return $instance;
    }

    protected function OnInit(Event $event)
    {
        ob_start();
    }

    protected function OnBeforeContentSend()
    {
        $render_time = microtime(true) - Request::getIncomeTime();
        $render_time = number_format($render_time*1000, 0, ",", " ");
        sys::headerQuiet("X-Render-Time: {$render_time} ms", true);
    }

    protected function sendHeadersFor($encoding)
    {
        sys::header("Content-Encoding: {$encoding}", true);
        sys::header("Vary: \"Content-Encoding\"");
    }

    function beforeSend($encoding = null)
    {
        if (ob_get_level()) {
            if (ob_get_length()) {
                exit(ob_get_clean());
            }
        }
        if (isset($encoding)) {
            $this->sendHeadersFor($encoding);
        }

        $this->OnBeforeContentSend();
    }

    protected function OnShutdown(Event $event)
    {
        if (! ob_get_level() || (($result = ob_get_clean()) === false) || empty($result)) {
            $this->OnBeforeContentSend();
            return;
        }
        $setled_content_type = null;
        foreach (headers_list() as $header) {
            $header = strtolower($header);
            if (strpos($header, "content-encoding:") === 0) {
                $this->OnBeforeContentSend();
                echo $result;
                return ;
            } elseif (strpos($header, "content-type:") === 0) {
                $setled_content_type = trim(substr($header, strlen("content-type:")));
            }
        }
        $default_content_type = strlen(ini_get("default_mimetype")) ? ini_get("default_mimetype") : "text/plain";
        $content_type = isset($setled_content_type) ? $setled_content_type : $default_content_type;
        $is_text = (strpos(strtolower(trim($content_type)), "text/") === 0);

        if (! $is_text) {
            $this->OnBeforeContentSend();
            echo $result;
            return;
        }
        if (Application::allowTextCompress()) {
            $allow_encodings = Request::getAllowedCompressors();
            if (ar::length($allow_encodings)) {
                try {
                    $encodedResult = encoder::encode($result, $allow_encodings[0]);
                    $best_compress = (strlen($result) == 0) ? 1 : strlen($encodedResult) / strlen($result);
                    $this->sendHeadersFor($allow_encodings[0]);
                    sys::headerQuiet('X-Content-Compressed: '.sprintf('%.1f%%', $best_compress*100), true);
                    $result = $encodedResult;
                } catch (Exception $e) {}
            }
        }

        sys::headerQuiet("Content-Length: ".strlen($result), true);
        $this->OnBeforeContentSend();
        echo $result;
    }
}

?>